package me.zhengjie.utils;



import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 日期工具类
 */
public class DateUtil{

    // ==格式到年==
    /**
     * 日期格式，年份，例如：2004，2008
     */
    public static final String DATE_FORMAT_YYYY = "yyyy";


    // ==格式到年月 ==
    /**
     * 日期格式，年份和月份，例如：200707，200808
     */
    public static final String DATE_FORMAT_YYYYMM = "yyyyMM";

    /**
     * 日期格式，年份和月份，例如：200707，2008-08
     */
    public static final String DATE_FORMAT_YYYY_MM = "yyyy-MM";


    // ==格式到年月日==
    /**
     * 日期格式，年月日，例如：050630，080808
     */
    public static final String DATE_FORMAT_YYMMDD = "yyMMdd";

    /**
     * 日期格式，年月日，用横杠分开，例如：06-12-25，08-08-08
     */
    public static final String DATE_FORMAT_YY_MM_DD = "yy-MM-dd";

    /**
     * 日期格式，年月日，例如：20050630，20080808
     */
    public static final String DATE_FORMAT_YYYYMMDD = "yyyyMMdd";

    /**
     * 日期格式，年月日，用横杠分开，例如：2006-12-25，2008-08-08
     */
    public static final String DATE_FORMAT_YYYY_MM_DD = "yyyy-MM-dd";

    /**
     * 日期格式，年月日，例如：2016.10.05
     */
    public static final String DATE_FORMAT_POINTYYYYMMDD = "yyyy.MM.dd";

    /**
     * 日期格式，年月日，例如：2016年10月05日
     */
    public static final String DATE_TIME_FORMAT_YYYY年MM月DD日 = "yyyy年MM月dd日";


    // ==格式到年月日 时分 ==

    /**
     * 日期格式，年月日时分，例如：200506301210，200808081210
     */
    public static final String DATE_FORMAT_YYYYMMDDHHmm = "yyyyMMddHHmm";

    /**
     * 日期格式，年月日时分，例如：20001230 12:00，20080808 20:08
     */
    public static final String DATE_TIME_FORMAT_YYYYMMDD_HH_MI = "yyyyMMdd HH:mm";

    /**
     * 日期格式，年月日时分，例如：2000-12-30 12:00，2008-08-08 20:08
     */
    public static final String DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI = "yyyy-MM-dd HH:mm";


    // ==格式到年月日 时分秒==
    /**
     * 日期格式，年月日时分秒，例如：20001230120000，20080808200808
     */
    public static final String DATE_TIME_FORMAT_YYYYMMDDHHMISS = "yyyyMMddHHmmss";

    /**
     * 日期格式，年月日时分秒，年月日用横杠分开，时分秒用冒号分开
     * 例如：2005-05-10 23：20：00，2008-08-08 20:08:08
     */
    public static final String DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS = "yyyy-MM-dd HH:mm:ss";


    // ==格式到年月日 时分秒 毫秒==
    /**
     * 日期格式，年月日时分秒毫秒，例如：20001230120000123，20080808200808456
     */
    public static final String DATE_TIME_FORMAT_YYYYMMDDHHMISSSSS = "yyyyMMddHHmmssSSS";


    // ==特殊格式==
    /**
     * 日期格式，月日时分，例如：10-05 12:00
     */
    public static final String DATE_FORMAT_MMDDHHMI = "MM-dd HH:mm";


    /* ************工具方法***************   */

    /**
     * 获取某日期的年份
     * @param date
     * @return
     */
    public static Integer getYear(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.YEAR);
    }

    /**
     * 获取某日期的月份
     * @param date
     * @return
     */
    public static Integer getMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.MONTH) + 1;
    }

    /**
     * 获取某日期的日数
     * @param date
     * @return
     */
    public static Integer getDay(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int day=cal.get(Calendar.DATE);//获取日
        return day;
    }

    public static Date monthCal(Date date, Integer type, Integer diff) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        //cal.add(Calendar.MONTH, diff);
        cal.add(type, diff);
        return cal.getTime();
    }

    /**
     * 格式化Date时间
     * @param time Date类型时间
     * @param timeFromat String类型格式
     * @return 格式化后的字符串
     */
    public static String parseDateToStr(Date time, String timeFromat){
        DateFormat dateFormat=new SimpleDateFormat(timeFromat);
        return dateFormat.format(time);
    }

    /**
     * 格式化Timestamp时间
     * @param timestamp Timestamp类型时间
     * @param timeFromat
     * @return 格式化后的字符串
     */
    public static String parseTimestampToStr(Timestamp timestamp,String timeFromat){
        SimpleDateFormat df = new SimpleDateFormat(timeFromat);
        return df.format(timestamp);
    }

    /**
     * 格式化Date时间
     * @param time Date类型时间
     * @param timeFromat String类型格式
     * @param defaultValue 默认值为当前时间Date
     * @return 格式化后的字符串
     */
    public static String parseDateToStr(Date time, String timeFromat, final Date defaultValue){
        try{
            DateFormat dateFormat=new SimpleDateFormat(timeFromat);
            return dateFormat.format(time);
        }catch (Exception e){
            if(defaultValue!=null)
                return parseDateToStr(defaultValue, timeFromat);
            else
                return parseDateToStr(new Date(), timeFromat);
        }
    }

    /**
     * 格式化Date时间
     * @param time Date类型时间
     * @param timeFromat String类型格式
     * @param defaultValue 默认时间值String类型
     * @return 格式化后的字符串
     */
    public static String parseDateToStr(Date time, String timeFromat, final String defaultValue){
        try{
            DateFormat dateFormat=new SimpleDateFormat(timeFromat);
            return dateFormat.format(time);
        }catch (Exception e){
            return defaultValue;
        }
    }

    /**
     * 格式化String时间
     * @param time String类型时间
     * @param timeFromat String类型格式
     * @return 格式化后的Date日期
     */
    public static Date parseStrToDate(String time, String timeFromat) {
        if (time == null || time.equals("")) {
            return null;
        }

        Date date=null;
        try{
            DateFormat dateFormat=new SimpleDateFormat(timeFromat);
            date=dateFormat.parse(time);
        }catch(Exception e){

        }
        return date;
    }

    /**
     * 格式化String时间
     * @param strTime String类型时间
     * @param timeFromat String类型格式
     * @param defaultValue 异常时返回的默认值
     * @return
     */
    public static Date parseStrToDate(String strTime, String timeFromat,
                                      Date defaultValue) {
        try {
            DateFormat dateFormat = new SimpleDateFormat(timeFromat);
            return dateFormat.parse(strTime);
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * 当strTime为2008-9时返回为2008-9-1 00:00格式日期时间，无法转换返回null.
     * @param strTime
     * @return
     */
    public static Date strToDate(String strTime) {
        if(strTime==null || strTime.trim().length()<=0)
            return null;

        Date date = null;
        List<String> list = new ArrayList<String>(0);

        list.add(DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS);
        list.add(DATE_TIME_FORMAT_YYYYMMDDHHMISSSSS);
        list.add(DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI);
        list.add(DATE_TIME_FORMAT_YYYYMMDD_HH_MI);
        list.add(DATE_TIME_FORMAT_YYYYMMDDHHMISS);
        list.add(DATE_FORMAT_YYYY_MM_DD);
        //list.add(DATE_FORMAT_YY_MM_DD);
        list.add(DATE_FORMAT_YYYYMMDD);
        list.add(DATE_FORMAT_YYYY_MM);
        list.add(DATE_FORMAT_YYYYMM);
        list.add(DATE_FORMAT_YYYY);


        for (Iterator iter = list.iterator(); iter.hasNext();) {
            String format = (String) iter.next();
            if(strTime.indexOf("-")>0 && format.indexOf("-")<0)
                continue;
            if(strTime.indexOf("-")<0 && format.indexOf("-")>0)
                continue;
            if(strTime.length()>format.length())
                continue;
            date = parseStrToDate(strTime, format);
            if (date != null)
                break;
        }

        return date;
    }

    /**
     * 解析两个日期之间的所有月份
     * @param beginDateStr 开始日期，至少精确到yyyy-MM
     * @param endDateStr 结束日期，至少精确到yyyy-MM
     * @return yyyy-MM日期集合
     */
    public static List<String> getMonthListOfDate(String beginDateStr, String endDateStr) {
        // 指定要解析的时间格式
        SimpleDateFormat f = new SimpleDateFormat("yyyy-MM");
        // 返回的月份列表
        String sRet = "";

        // 定义一些变量
        Date beginDate = null;
        Date endDate = null;

        GregorianCalendar beginGC = null;
        GregorianCalendar endGC = null;
        List<String> list = new ArrayList<String>();

        try {
            // 将字符串parse成日期
            beginDate = f.parse(beginDateStr);
            endDate = f.parse(endDateStr);

            // 设置日历
            beginGC = new GregorianCalendar();
            beginGC.setTime(beginDate);

            endGC = new GregorianCalendar();
            endGC.setTime(endDate);

            // 直到两个时间相同
            while (beginGC.getTime().compareTo(endGC.getTime()) <= 0) {
                sRet = beginGC.get(Calendar.YEAR) + "-"
                        + (beginGC.get(Calendar.MONTH) + 1);
                list.add(sRet);
                // 以月为单位，增加时间
                beginGC.add(Calendar.MONTH, 1);
            }
            return list;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 解析两个日期段之间的所有日期
     * @param beginDateStr 开始日期  ，至少精确到yyyy-MM-dd
     * @param endDateStr 结束日期  ，至少精确到yyyy-MM-dd
     * @return yyyy-MM-dd日期集合
     */
    public static List<String> getDayListOfDate(String beginDateStr, String endDateStr) {
        // 指定要解析的时间格式
        SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");

        // 定义一些变量
        Date beginDate = null;
        Date endDate = null;

        Calendar beginGC = null;
        Calendar endGC = null;
        List<String> list = new ArrayList<String>();

        try {
            // 将字符串parse成日期
            beginDate = f.parse(beginDateStr);
            endDate = f.parse(endDateStr);

            // 设置日历
            beginGC = Calendar.getInstance();
            beginGC.setTime(beginDate);

            endGC = Calendar.getInstance();
            endGC.setTime(endDate);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

            // 直到两个时间相同
            while (beginGC.getTime().compareTo(endGC.getTime()) <= 0) {

                list.add(sdf.format(beginGC.getTime()));
                // 以日为单位，增加时间
                beginGC.add(Calendar.DAY_OF_MONTH, 1);
            }
            return list;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取当下年份指定前后数量的年份集合
     * @param before 当下年份前年数
     * @param behind 当下年份后年数
     * @return 集合
     */
    public static List<Integer> getYearListOfYears(int before,int behind) {
        if (before<0 || behind<0) {
            return null;
        }
        List<Integer> list = new ArrayList<Integer>();
        Calendar c = null;
        c = Calendar.getInstance();
        c.setTime(new Date());
        int currYear = Calendar.getInstance().get(Calendar.YEAR);

        int startYear = currYear - before;
        int endYear = currYear + behind;
        for (int i = startYear; i < endYear; i++) {
            list.add(Integer.valueOf(i));
        }
        return list;
    }

    /**
     * 获取当前日期是一年中第几周
     * @param date
     * @return
     */
    public static Integer getWeekthOfYear(Date date) {
        Calendar c = new GregorianCalendar();
        c.setFirstDayOfWeek(Calendar.MONDAY);
        c.setMinimalDaysInFirstWeek(7);
        c.setTime(date);

        return c.get(Calendar.WEEK_OF_YEAR);
    }

    /**
     * 获取某一年各星期的始终时间
     * 实例：getWeekList(2016)，第52周(从2016-12-26至2017-01-01)
     * @param 年份
     * @return
     */
    public static HashMap<Integer,String> getWeekTimeOfYear(int year) {
        HashMap<Integer,String> map = new LinkedHashMap<Integer,String>();
        Calendar c = new GregorianCalendar();
        c.set(year, Calendar.DECEMBER, 31, 23, 59, 59);
        int count = getWeekthOfYear(c.getTime());

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dayOfWeekStart = "";
        String dayOfWeekEnd = "";
        for (int i = 1; i <= count; i++) {
            dayOfWeekStart = sdf.format(getFirstDayOfWeek(year, i));
            dayOfWeekEnd = sdf.format(getLastDayOfWeek(year, i));
            map.put(Integer.valueOf(i), "第"+i+"周(从"+dayOfWeekStart + "至" + dayOfWeekEnd+")");
        }
        return map;

    }

    /**
     * 获取某一年的总周数
     * @param year
     * @return
     */
    public static Integer getWeekCountOfYear(int year){
        Calendar c = new GregorianCalendar();
        c.set(year, Calendar.DECEMBER, 31, 23, 59, 59);
        int count = getWeekthOfYear(c.getTime());
        return count;
    }

    /**
     * 获取指定日期所在周的第一天
     * @param date
     * @return
     */
    public static Date getFirstDayOfWeek(Date date) {
        Calendar c = new GregorianCalendar();
        c.setFirstDayOfWeek(Calendar.MONDAY);
        c.setTime(date);
        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek()); // Monday
        return c.getTime();
    }

    /**
     * 获取指定日期所在周的最后一天
     * @param date
     * @return
     */
    public static Date getLastDayOfWeek(Date date) {
        Calendar c = new GregorianCalendar();
        c.setFirstDayOfWeek(Calendar.MONDAY);
        c.setTime(date);
        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek() + 6); // Sunday
        return c.getTime();
    }

    /**
     * 获取某年某周的第一天
     * @param year 目标年份
     * @param week 目标周数
     * @return
     */
    public static Date getFirstDayOfWeek(int year, int week) {
        Calendar c = new GregorianCalendar();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, Calendar.JANUARY);
        c.set(Calendar.DATE, 1);

        Calendar cal = (GregorianCalendar) c.clone();
        cal.add(Calendar.DATE, week * 7);

        return getFirstDayOfWeek(cal.getTime());
    }

    /**
     * 获取某年某周的最后一天
     * @param year 目标年份
     * @param week 目标周数
     * @return
     */
    public static Date getLastDayOfWeek(int year, int week) {
        Calendar c = new GregorianCalendar();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, Calendar.JANUARY);
        c.set(Calendar.DATE, 1);

        Calendar cal = (GregorianCalendar) c.clone();
        cal.add(Calendar.DATE, week * 7);

        return getLastDayOfWeek(cal.getTime());
    }

    /**
     * 获取某年某月的第一天
     * @param year 目标年份
     * @param month 目标月份
     * @return
     */
    public static Date getFirstDayOfMonth(int year,int month){
        month = month-1;
        Calendar   c   =   Calendar.getInstance();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, month);

        int day = c.getActualMinimum(c.DAY_OF_MONTH);

        c.set(Calendar.DAY_OF_MONTH, day);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        return c.getTime();
    }

    /**
     * 获取某年某月的最后一天
     * @param year 目标年份
     * @param month 目标月份
     * @return
     */
    public static Date getLastDayOfMonth(int year,int month){
        month = month-1;
        Calendar   c   =   Calendar.getInstance();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, month);
        int day = c.getActualMaximum(c.DAY_OF_MONTH);
        c.set(Calendar.DAY_OF_MONTH, day);
        c.set(Calendar.HOUR_OF_DAY, 23);
        c.set(Calendar.MINUTE, 59);
        c.set(Calendar.SECOND, 59);
        c.set(Calendar.MILLISECOND, 999);
        return c.getTime();
    }

    /**
     * 获取某个日期为星期几
     * @param date
     * @return String "星期*"
     */
    public static String getDayWeekOfDate1(Date date) {
        String[] weekDays = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);

        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0)
            w = 0;

        return weekDays[w];
    }

    /**
     * 获得指定日期的星期几数
     * @param date
     * @return int
     */
    public static Integer getDayWeekOfDate2(Date date){
        Calendar aCalendar = Calendar.getInstance();
        aCalendar.setTime(date);
        int weekDay = aCalendar.get(Calendar.DAY_OF_WEEK);
        return weekDay;
    }

    /**
     * 验证字符串是否为日期
     * 验证格式:YYYYMMDD、YYYY_MM_DD、YYYYMMDDHHMISS、YYYYMMDD_HH_MI、YYYY_MM_DD_HH_MI、YYYYMMDDHHMISSSSS、YYYY_MM_DD_HH_MI_SS
     * @param strTime
     * @return null时返回false;true为日期，false不为日期
     */
    public static boolean validateIsDate(String strTime) {
        if (strTime == null || strTime.trim().length() <= 0)
            return false;

        Date date = null;
        List<String> list = new ArrayList<String>(0);

        list.add(DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS);
        list.add(DATE_TIME_FORMAT_YYYYMMDDHHMISSSSS);
        list.add(DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI);
        list.add(DATE_TIME_FORMAT_YYYYMMDD_HH_MI);
        list.add(DATE_TIME_FORMAT_YYYYMMDDHHMISS);
        list.add(DATE_FORMAT_YYYY_MM_DD);
        //list.add(DATE_FORMAT_YY_MM_DD);
        list.add(DATE_FORMAT_YYYYMMDD);
        //list.add(DATE_FORMAT_YYYY_MM);
        //list.add(DATE_FORMAT_YYYYMM);
        //list.add(DATE_FORMAT_YYYY);

        for (Iterator iter = list.iterator(); iter.hasNext();) {
            String format = (String) iter.next();
            if(strTime.indexOf("-")>0 && format.indexOf("-")<0)
                continue;
            if(strTime.indexOf("-")<0 && format.indexOf("-")>0)
                continue;
            if(strTime.length()>format.length())
                continue;
            date = parseStrToDate(strTime.trim(), format);
            if (date != null)
                break;
        }

        if (date != null) {
            System.out.println("生成的日期:"+DateUtil.parseDateToStr(date, DateUtil.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS, "--null--"));
            return true;
        }
        return false;
    }

    /**
     * 将指定日期的时分秒格式为零
     * @param date
     * @return
     */
    public static Date formatHhMmSsOfDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * 获得指定时间加减参数后的日期(不计算则输入0)
     * @param date 指定日期
     * @param year 年数，可正可负
     * @param month 月数，可正可负
     * @param day 天数，可正可负
     * @param hour 小时数，可正可负
     * @param minute 分钟数，可正可负
     * @param second 秒数，可正可负
     * @param millisecond 毫秒数，可正可负
     * @return 计算后的日期
     */
    public static Date addDate(Date date,int year,int month,int day,int hour,int minute,int second,int millisecond){
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.YEAR, year);//加减年数
        c.add(Calendar.MONTH, month);//加减月数
        c.add(Calendar.DATE, day);//加减天数
        c.add(Calendar.HOUR,hour);//加减小时数
        c.add(Calendar.MINUTE, minute);//加减分钟数
        c.add(Calendar.SECOND, second);//加减秒
        c.add(Calendar.MILLISECOND, millisecond);//加减毫秒数

        return c.getTime();
    }

    /**
     * 获得两个日期的时间戳之差
     * @param startDate
     * @param endDate
     * @return
     */
    public static Long getDistanceTimestamp(Date startDate,Date endDate){
        long daysBetween=(endDate.getTime()-startDate.getTime()+1000000)/(3600*24*1000);
        return daysBetween;
    }

    /**
     * 判断二个时间是否为同年同月
     * @param date1
     * @param date2
     * @return
     */
    public static Boolean compareIsSameMonth(Date date1,Date date2){
        boolean flag = false;
        int year1  = getYear(date1);
        int year2 = getYear(date2);
        if(year1 == year2){
            int month1 = getMonth(date1);
            int month2 = getMonth(date2);
            if(month1 == month2)flag = true;
        }
        return flag;
    }

    /**
     * 获得两个时间相差距离多少天多少小时多少分多少秒
     * @param str1 时间参数 1 格式：1990-01-01 12:00:00
     * @param str2 时间参数 2 格式：2009-01-01 12:00:00
     * @return long[] 返回值为：{天, 时, 分, 秒}
     */
    public static long[] getDistanceTime(Date one, Date two) {
        long day = 0;
        long hour = 0;
        long min = 0;
        long sec = 0;
        try {

            long time1 = one.getTime();
            long time2 = two.getTime();
            long diff ;
            if(time1<time2) {
                diff = time2 - time1;
            } else {
                diff = time1 - time2;
            }
            day = diff / (24 * 60 * 60 * 1000);
            hour = (diff / (60 * 60 * 1000) - day * 24);
            min = ((diff / (60 * 1000)) - day * 24 * 60 - hour * 60);
            sec = (diff/1000-day*24*60*60-hour*60*60-min*60);
        } catch (Exception e) {
            e.printStackTrace();
        }
        long[] times = {day, hour, min, sec};
        return times;
    }

    /**
     * 两个时间相差距离多少天多少小时多少分多少秒
     * @param str1 时间参数 1 格式：1990-01-01 12:00:00
     * @param str2 时间参数 2 格式：2009-01-01 12:00:00
     * @return String 返回值为：{天, 时, 分, 秒}
     */
    public static long[] getDistanceTime(String str1, String str2) {
        DateFormat df = new SimpleDateFormat(DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS);
        Date one;
        Date two;
        long day = 0;
        long hour = 0;
        long min = 0;
        long sec = 0;
        try {
            one = df.parse(str1);
            two = df.parse(str2);
            long time1 = one.getTime();
            long time2 = two.getTime();
            long diff ;
            if(time1<time2) {
                diff = time2 - time1;
            } else {
                diff = time1 - time2;
            }
            day = diff / (24 * 60 * 60 * 1000);
            hour = (diff / (60 * 60 * 1000) - day * 24);
            min = ((diff / (60 * 1000)) - day * 24 * 60 - hour * 60);
            sec = (diff/1000-day*24*60*60-hour*60*60-min*60);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        long[] times = {day, hour, min, sec};
        return times;
    }

    /**
     * 两个时间之间相差距离多少天
     * @param one 时间参数 1：
     * @param two 时间参数 2：
     * @return 相差天数
     */
    public static Long getDistanceDays(String str1, String str2) throws Exception{
        DateFormat df = new SimpleDateFormat(DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS);
        Date one;
        Date two;
        long days=0;
        try {
            one = df.parse(str1);
            two = df.parse(str2);
            long time1 = one.getTime();
            long time2 = two.getTime();
            long diff ;
            if(time1<time2) {
                diff = time2 - time1;
            } else {
                diff = time1 - time2;
            }
            days = diff / (1000 * 60 * 60 * 24);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return days;
    }

    /**
     * 获取指定时间的那天 00:00:00.000 的时间
     * @param date
     * @return
     */
    public static Date getDayBeginTime(final Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        return c.getTime();
    }

    /**
     * 获取指定时间的那天 23:59:59.999 的时间
     * @param date
     * @return
     */
    public static Date getDayEndTime(final Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.HOUR_OF_DAY, 23);
        c.set(Calendar.MINUTE, 59);
        c.set(Calendar.SECOND, 59);
        c.set(Calendar.MILLISECOND, 999);
        return c.getTime();
    }

    public static Map<Integer, List<String>> getResults(String a, String b) throws ParseException {
//        a = "2017-12-01";
//        b = "2018-02-02";

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd");
        Date ad = sdf.parse(a);
        Date bd = sdf.parse(b);

        Calendar cl1 = Calendar.getInstance();
        cl1.setTime(ad);
        Calendar cl2 = Calendar.getInstance();
        cl2.setTime(bd);

        System.out.println(cl1.get(Calendar.YEAR) + "-" + cl1.get(Calendar.DAY_OF_WEEK));

        Map<Integer, List<String>> result = new HashMap<Integer, List<String>>();

        int num = 0;

        while (true) {
            if (cl2.compareTo(cl1) <= 0) {
                break;
            }

            int count = 7;

            if (num == 0) {
                int day = cl1.get(Calendar.DAY_OF_WEEK) - 1;
                day = day == 0 ? 7 : day;
                count = 7 - day + 1;
            }
            if (!result.containsKey(num)) {
                result.put(num, new ArrayList<String>());
            }

            for (int i = 0; i < count; i++) {
                result.get(num).add(sdf.format(cl1.getTime()));
                cl1.add(Calendar.DAY_OF_WEEK, 1);
                if (cl2.compareTo(cl1) <= 0) {
                    break;
                }
            }
            num++;
        }
//        List<String> time = new ArrayList<String>();
//        for (Map.Entry<Integer, List<String>> entry : result.entrySet()) {
//            List<String> temp = entry.getValue();
//            String str = temp.get(0) + "~" + temp.get(temp.size() - 1);
//            time.add(str);
//        }
        return result;
    }


    /**
     * 根据一段时间区间，按月份拆分成多个时间段
     * @param startDate 开始日期
     * @param endDate  结束日期
     * @return
     */
    public static List<KeyValueForDate> getKeyValueForDate(String startDate,String endDate) {
            List<KeyValueForDate> list = null;
            try {
                list = new ArrayList<KeyValueForDate>();

                String firstDay = "";
                String lastDay = "";
                Date d1 = new SimpleDateFormat("yyyy-MM-dd").parse(startDate);// 定义起始日期

                Date d2 = new SimpleDateFormat("yyyy-MM-dd").parse(endDate);// 定义结束日期

                Calendar dd = Calendar.getInstance();// 定义日期实例
                dd.setTime(d1);// 设置日期起始时间
                Calendar cale = Calendar.getInstance();

                Calendar c = Calendar.getInstance();
                c.setTime(d2);

                int startDay = d1.getDate();
                int endDay = d2.getDate();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

                KeyValueForDate keyValueForDate = null;

                while (dd.getTime().before(d2)) {// 判断是否到结束日期
                    keyValueForDate = new KeyValueForDate();
                    cale.setTime(dd.getTime());

                    if(dd.getTime().equals(d1)){
                        cale.set(Calendar.DAY_OF_MONTH, dd
                                .getActualMaximum(Calendar.DAY_OF_MONTH));
                        lastDay = sdf.format(cale.getTime());
                        keyValueForDate.setStartDate(sdf.format(d1));
                        keyValueForDate.setEndDate(lastDay);

                    }else if(dd.get(Calendar.MONTH) == d2.getMonth() && dd.get(Calendar.YEAR) == c.get(Calendar.YEAR)){
                        cale.set(Calendar.DAY_OF_MONTH,1);//取第一天
                        firstDay = sdf.format(cale.getTime());

                        keyValueForDate.setStartDate(firstDay);
                        keyValueForDate.setEndDate(sdf.format(d2));

                    }else {
                        cale.set(Calendar.DAY_OF_MONTH,1);//取第一天
                        firstDay = sdf.format(cale.getTime());

                        cale.set(Calendar.DAY_OF_MONTH, dd
                                .getActualMaximum(Calendar.DAY_OF_MONTH));
                        lastDay = sdf.format(cale.getTime());

                        keyValueForDate.setStartDate(firstDay);
                        keyValueForDate.setEndDate(lastDay);

                    }
                    list.add(keyValueForDate);
                    dd.add(Calendar.MONTH, 1);// 进行当前日期月份加1

                }

                if(endDay<startDay){
                    keyValueForDate = new KeyValueForDate();

                    cale.setTime(d2);
                    cale.set(Calendar.DAY_OF_MONTH,1);//取第一天
                    firstDay = sdf.format(cale.getTime());

                    keyValueForDate.setStartDate(firstDay);
                    keyValueForDate.setEndDate(sdf.format(d2));
                    list.add(keyValueForDate);
                }
            } catch (ParseException e) {
                return null;
            }

            return list;
        }




    public static void main(String[] args) throws ParseException {
        String startTime="2019-07-28 18:40:30";
        String endTime="2019-11-30 01:00:00";
        int type=2;
        System.out.println(queryInterval( startTime,  endTime, type));
        for(String str: getLast30Days()) {
            System.out.println(str);
        }
    }

    public static List<String[]> getType(Date sd , Date ed){
         SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        long days = (ed.getTime() - sd.getTime()) / 3600 / 24 / 1000;

        Calendar instance = Calendar.getInstance();
        instance.setTime(sd);
        int i = instance.get(Calendar.DAY_OF_WEEK);
        int fsi = 7 - i + 1;
        long iiv = days - fsi;

        //天数
        long d = iiv / 7;

        instance.add(Calendar.DAY_OF_YEAR, fsi);

        List<String[]> list = new ArrayList<>();
        list.add(new String[]{df.format(sd), df.format(instance.getTime())});

        String[] ne ;
        for (long k = 0; k < d; k++) {
        instance.add(Calendar.DAY_OF_YEAR, 1);
        Date start = instance.getTime();
        instance.add(Calendar.DAY_OF_YEAR, 6);
         Date end = instance.getTime();
        ne = new String[]{df.format(start), df.format(end)};
        list.add(ne);
         }

         instance.add(Calendar.DAY_OF_YEAR, 1);
        list.add(new String[]{df.format(instance.getTime()), df.format(ed)});

        return list;
    }


//
//
//
//    public static void main(String [] args){
//        try {
//              System.out.println(getResults("2017-12-01","2018-02-02"));
////            DateUtil dateUtil = new DateUtil();
////            System.out.println();
//
//        } catch (Exception e) {
//            // TODO: handle exception
//        }
//
//    }
    /**
     * 通过开始时间和结束时间查询中间的每个月的开始和结束时间
     * @param startTime
     * @param endTime
     * @return
     * @throws ParseException
     */
    public static List<Map<String, String>> queryIntervalMonth(String startTime, String endTime) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        Calendar bef = Calendar.getInstance();
        Calendar aft = Calendar.getInstance();
        bef.setTime(sdf.parse(startTime));
        aft.setTime(sdf.parse(endTime));
        int result = aft.get(Calendar.MONTH) - bef.get(Calendar.MONTH);
        int month = (aft.get(Calendar.YEAR) - bef.get(Calendar.YEAR)) * 12;
        List<Map<String, String>> mapList = Lists.newArrayList();
        int minMonth = Math.abs(month + result);
        Map<String, String> dateMap = Maps.newHashMap();
        if(minMonth>0){
            dateMap.put("start", startTime);
            dateMap.put("end", getMaxMonthDate(startTime) + " 23:59:59");
            mapList.add(dateMap);
            for (int i = 0; i < minMonth; i++) {
                dateMap = Maps.newHashMap();
                Calendar start = Calendar.getInstance();
                start.setTime(sdf.parse(startTime));
                start.add(Calendar.MONTH, 1);
                startTime = parseDateToStr(start.getTime(), DateUtil.DATE_FORMAT_YY_MM_DD);
                dateMap.put("start", getMinMonthDate(startTime) + " 00:00:00");
                if(i+1 == minMonth){
                    dateMap.put("end", endTime);
                }else{
                    dateMap.put("end", getMaxMonthDate(startTime) + " 23:59:59");
                }
                mapList.add(dateMap);
            }
        }else{
            dateMap.put("start", startTime);
            dateMap.put("end", endTime);
            mapList.add(dateMap);
        }
        return mapList;
    }
    static SimpleDateFormat dateFormat = new SimpleDateFormat(DateUtil.DATE_FORMAT_YYYY_MM_DD);
    /**
     * 获取月份起始日期
     * @param date
     * @return
     * @throws ParseException
     */
    public static String getMinMonthDate(String date) throws ParseException{
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dateFormat.parse(date));
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
        return dateFormat.format(calendar.getTime());
    }

    /**
     * 获取月份最后日期
     * @param date
     * @return
     * @throws ParseException
     */
    public static String getMaxMonthDate(String date) throws ParseException{
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dateFormat.parse(date));
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        System.out.println(dateFormat.format(calendar.getTime()));
        return dateFormat.format(calendar.getTime());
    }

    /**
     * 获取年份起始日期
     * @param date
     * @return
     * @throws ParseException
     */
    public static String getMinYearDate(String date) throws ParseException{
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dateFormat.parse(date));
        return dateFormat.format(calendar.getTime());
    }

    /**
     * 获取年份最后日期
     * @param date
     * @return
     * @throws ParseException
     */
    public static String getMaxYearDate(String date) throws ParseException{
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dateFormat.parse(date));
        calendar.set(Calendar.DAY_OF_YEAR,1);
        calendar.roll(Calendar.DAY_OF_YEAR, -1);
        return dateFormat.format(calendar.getTime());
    }


    /**
     * 通过开始时间和结束时间查询中间的每个月的开始和结束时间
     * @param startTime
     * @param endTime
     * @return
     * @throws ParseException
     */
    public static List<Map<String, String>> queryInterval(String startTime, String endTime,int type) throws ParseException {
        /*
            type 1:月 2:季度 3:年
         */
        if(type==1){
            return queryIntervalMonth(startTime, endTime);
        }else if(type==2){
            return queryIntervalQuarter(startTime, endTime);
        }else{
            return queryIntervalYear(startTime, endTime);
        }
    }

    /**
     * 通过开始时间和结束时间查询中间的每个月的开始和结束时间
     * @param startTime
     * @param endTime
     * @return
     * @throws ParseException
     */
    public static List<Map<String, String>> queryInterval(Date startTime, Date endTime,int type) throws ParseException {
        return queryInterval(DateUtil.parseDateToStr(startTime,DateUtil.DATE_FORMAT_YY_MM_DD),DateUtil.parseDateToStr(endTime,DateUtil.DATE_FORMAT_YY_MM_DD),type);
    }

    private static List<Map<String,String>> queryIntervalYear(String startTime, String endTime) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        Calendar bef = Calendar.getInstance();
        Calendar aft = Calendar.getInstance();
        bef.setTime(sdf.parse(startTime));
        aft.setTime(sdf.parse(endTime));
        int year = (aft.get(Calendar.YEAR) - bef.get(Calendar.YEAR));
        List<Map<String, String>> mapList = Lists.newArrayList();
        Map<String, String> dateMap = Maps.newHashMap();
        dateMap.put("start", startTime);
        if(year>0){
            dateMap.put("end", getMaxYearDate(startTime) + " 23:59:59");
            mapList.add(dateMap);
            for (int i = 0; i < year; i++) {
                dateMap = Maps.newHashMap();
                bef.add(Calendar.YEAR, 1);
                dateMap.put("start", DateUtil.parseDateToStr(getYearFirst(Integer.parseInt(DateUtil.parseDateToStr(bef.getTime(),"yyyy"))),DateUtil.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS));
                if (i + 1 == year) {
                    dateMap.put("end", endTime);
                }else{
                    dateMap.put("end", getMaxYearDate(DateUtil.parseDateToStr(bef.getTime(),DateUtil.DATE_FORMAT_YYYY_MM_DD))+" 23:59:59");
                }
                mapList.add(dateMap);
            }
        }else{
            dateMap.put("end", endTime);
            mapList.add(dateMap);
        }
        return mapList;
    }

    private static List<Map<String,String>> queryIntervalQuarter(String startTime, String endTime) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        Calendar bef = Calendar.getInstance();
        Calendar aft = Calendar.getInstance();
        bef.setTime(sdf.parse(startTime));
        aft.setTime(sdf.parse(endTime));
        int thisMonth = bef.get(Calendar.MONTH)+1; //当前月
        int result = aft.get(Calendar.MONTH) - bef.get(Calendar.MONTH);
        int month = (aft.get(Calendar.YEAR) - bef.get(Calendar.YEAR)) * 12;
        List<Map<String, String>> mapList = Lists.newArrayList();
        Map<String, String> dateMap = Maps.newHashMap();
        dateMap.put("start",startTime);
        int minMonth = Math.abs(month + result);
        if(thisMonth == 1 || thisMonth==4 || thisMonth==7 || thisMonth==10){
            bef.add(Calendar.MONTH, 2);
            minMonth-=2;
        }else if(thisMonth == 2 || thisMonth==5 || thisMonth==8 || thisMonth==11){
            bef.add(Calendar.MONTH, 1);
            minMonth-=1;
        }
        dateMap.put("end",getMaxMonthDate(parseDateToStr(bef.getTime(), DateUtil.DATE_FORMAT_YYYY_MM_DD))+" 23:59:59");
        mapList.add(dateMap);
        bef.add(Calendar.MONTH, 1);
        startTime = getMinMonthDate(parseDateToStr(bef.getTime(), DateUtil.DATE_FORMAT_YYYY_MM_DD))+" 00:00:00";
        while (minMonth > 0) {
            dateMap = Maps.newHashMap();
            dateMap.put("start",startTime);
            Calendar end = Calendar.getInstance();
            end.setTime(sdf.parse(startTime));
            end.add(Calendar.MONTH, 2);
            minMonth -= 3;
            if(minMonth>0){
                dateMap.put("end",getMaxMonthDate(parseDateToStr(end.getTime(), DateUtil.DATE_FORMAT_YYYY_MM_DD))+" 23:59:59");
            }else{
                dateMap.put("end",endTime);
            }
            mapList.add(dateMap);
            bef.add(Calendar.MONTH, 3);
            startTime = getMinMonthDate(parseDateToStr(bef.getTime(), DateUtil.DATE_FORMAT_YYYY_MM_DD))+" 00:00:00";
        }
        return mapList;
    }

    public static Date getCurrYearFirst(){
        Calendar currCal=Calendar.getInstance();
        int currentYear = currCal.get(Calendar.YEAR);
        return getYearFirst(currentYear);
    }

    /**
     * 获取某年第一天日期
     * @param year 年份
     * @return Date
     */
    public static Date getYearFirst(int year){
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        Date currYearFirst = calendar.getTime();
        return currYearFirst;
    }


    /**
     * 获取近30天的天数
     * @return
     */
    public static String[] getLast30Days() {
        int daysInterval = 30 ;
        String[] days = new String[daysInterval];

        Calendar calendar = Calendar.getInstance();
        long current = System.currentTimeMillis();
        calendar.setTimeInMillis(current-24l*3600*1000*daysInterval);
        final long mills = calendar.getTimeInMillis() ;

        for(int i=0; i<30; i++) {
            calendar.setTimeInMillis(mills+(i+1)*24*3600*1000l);
            days[i] = parseDateToStr(calendar.getTime(),DATE_FORMAT_YYYYMMDD);
        }
        return days;
    }

    /**
     * 返回数据库格式时间戳
     * @return
     */
    public static java.sql.Timestamp getCurrentTimestamp() {
        return new java.sql.Timestamp(System.currentTimeMillis());
    }


    /**
     * 获取格林威治秒数
     * @param timestamp
     * @return
     */
    public static Long getUTCSeconds(String timestamp) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        Date datetime = parseStrToDate(timestamp,DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS);
        calendar.setTime(datetime);
        TimeZone timeZone = TimeZone.getTimeZone("GMT+08:00");
        calendar.setTimeZone(timeZone);
        return calendar.getTimeInMillis()/1000;
    }
}
